package la.iok.hzsvn.lewin.movie.service;

import la.iok.hzsvn.lewin.movie.core.Token;
import la.iok.hzsvn.lewin.movie.core.model.MovieVo;
import la.iok.hzsvn.lewin.movie.core.movieservice.param.MovieVersionListParam;
import la.iok.hzsvn.lewin.movie.entity.MovieInstance;
import la.iok.hzsvn.lewin.movie.model.MovieDeleteContext;
import la.iok.hzsvn.lewin.movie.model.PublishParam;
import la.iok.hzsvn.lewin.mybatis.model.PageParam;
import la.iok.hzsvn.lewin.mybatis.model.PageVo;
import la.iok.hzsvn.lewin.mybatis.model.SortParam;
import la.iok.hzsvn.lewin.mybatis.service.BaseService;
import la.iok.hzsvn.redis.model.ProgressKey;
import la.iok.hzsvn.share.annotations.NotNull;
import la.iok.hzsvn.share.annotations.NotNullElement;
import la.iok.hzsvn.share.annotations.Nullable;

import java.util.List;

public interface MovieInstanceService extends BaseService<MovieInstance, Long> {

    /**
     * 发布剧本
     * @param token 操作用户
     * @param id 剧本id
     * @param param 发布参数
     * @param progressKey 进度的key
     * @return 新发布剧本实例id
     */
    Long publish(@NotNull Token token, @Nullable Long id, @NotNull PublishParam param, @Nullable ProgressKey progressKey);

    /**
     * 发布剧本
     * @param token 操作用户
     * @param id 剧本id
     * @param param 发布参数
     * @return 新发布剧本实例id
     */
    Long publish(@NotNull Token token, @Nullable Long id, @NotNull PublishParam param);

    /**
     * 分页查询列表
     * @param page 页号
     * @param limit 分页大小
     * @param orderColumn 排序字段
     * @param order 排序,ascending为升序,其他为降序
     * @param name 名称,模糊查询
     * @param author 作者,模糊查询
     * @param tag 标签,模糊查询
     * @param minPlayers 最少玩家数量
     * @param maxPlayers 最多玩家数量
     * @param minDuration 最小时长
     * @param maxDuration 最多时长
     * @param movieLevelId 剧本类别
     * @param status 剧本状态,如果为null则是所有状态
     * @param excludeLocal 是否排除设备本地剧本列表,1:排除,0：不排除
     * @param deviceCode excludeLocal为1时有效,需要排除的设备编码
     * @return 剧本列表
     */
    PageVo<MovieVo> page(int page, int limit,@Nullable String orderColumn, @Nullable String order, @Nullable String name,
                         @Nullable String author, @Nullable String tag, @Nullable Integer minPlayers, @Nullable Integer maxPlayers,
                         @Nullable Integer minDuration, @Nullable Integer maxDuration, @Nullable Long movieLevelId,
                         @Nullable Integer status,Integer excludeLocal,String deviceCode, Long[] innerTestIds);

    PageVo<MovieVo> page(@Nullable Token token,int page, int limit,@Nullable String orderColumn, @Nullable String order, @Nullable String name,
                         @Nullable String author, @Nullable String tag, @Nullable Integer minPlayers, @Nullable Integer maxPlayers,
                         @Nullable Integer minDuration, @Nullable Integer maxDuration, @Nullable Long movieLevelId,
                         Integer excludeLocal,String deviceCode);

    PageVo<MovieVo> page(int page, int limit,@Nullable String orderColumn, @Nullable String order, @Nullable String name,
                         @Nullable String author, @Nullable String tag, @Nullable Integer minPlayers, @Nullable Integer maxPlayers,
                         @Nullable Integer minDuration, @Nullable Integer maxDuration, @Nullable Long movieLevelId,
                         @Nullable Integer status);

    /**
     * 查询剧本所有发布的实例
     * @param token 操作用户。目前必须是超级管理员
     * @param movieId 剧本id,非实例id
     */
    @NotNull
    @NotNullElement
    List<MovieVo> publishes(@NotNull Token token, @Nullable Long movieId);

    /**
     * 获取剧本最新的实例
     * @param movieId 剧本id
     * @return 剧本最新的实例
     */
    @Nullable
    MovieInstance mostRecent(@Nullable Long movieId);

    @NotNull
    MovieVo po2vo(@NotNull MovieInstance movie);

    /**
     * 剧本上线
     * @param token 操作用户
     * @param movieId 剧本id
     */
    void online(@NotNull Token token, @NotNull Long movieId);

    /**
     * 剧本下线
     * @param token 操作用户
     * @param movieId 剧本id
     */
    void offline(@NotNull Token token, @NotNull Long movieId);

    /**
     * 更新剧本的级别。只更新最近一个实例的级别及剧本本身的级别
     * @param token 操作用户
     * @param movieId 剧本id
     * @param movieLevelId 级别id
     */
    void updateLevel(@NotNull Token token, @NotNull Long movieId, @NotNull Long movieLevelId);

    /**
     * 统计剧本数量
     * @param status 剧本状态。Admin可以查看在线和不在线的剧本,其他人只能查看在线的剧本
     * @return 剧本数量
     */
    int count(@Nullable Integer status);

    /**
     * 查询对应版本的剧本实例
     * @param movieId 剧本id
     * @param version 剧本版本,必须是完整匹配
     * @return 剧本实例
     */
    @Nullable
    MovieInstance movieInst(@Nullable Long movieId, @Nullable String version);

    /**
     * 查询对应版本的剧本实例,如果不存在则抛出异常
     * @param movieId 剧本id
     * @param version 剧本版本,必须是完整匹配
     * @return 剧本实例
     */
    @NotNull
    MovieInstance movieInst2(@Nullable Long movieId, @Nullable String version);

    /**
     * 增加剧本开本次数。指定实例开本次数增加1,其他版本实例不变。剧本开本次数增加1
     * @param movieId 剧本id
     * @param version 剧本版本
     */
    void incrementPlayTimes(@Nullable Long movieId, @Nullable String version);

    /**
     * 删除指定版本的剧本.需要先删除剧本的文件
     * @param token 操作用户
     * @param movieId 剧本id
     * @param version 剧本的版本
     */
    void delete(@NotNull Token token, @Nullable Long movieId, @Nullable String version);

    /**
     * 删除指定的剧本实例
     * @param token 操作用户
     * @param id 剧本版本实例id
     */
    void delete(@NotNull Token token, Long id);

    /**
     * 删除剧本实例的文件。遍历剧本使用的文件，将文件的引用计数减1并设置关联子表的记录为已经删除剧本文件
     * @param token 操作用户
     * @param movieId 剧本id
     * @param version 剧本版本
     * @return 剧本引用文件信息，后续做文件删除处理
     */
    MovieDeleteContext deleteMovieFiles(@NotNull Token token, @Nullable Long movieId, @Nullable String version);

    /**
     * 删除指定版本的剧本文件
     * @param token 操作用户
     * @param movieInstanceId 剧本版本实例id
     * @return 剧本引用文件信息，后续做文件删除处理
     */
    MovieDeleteContext deleteMovieFiles(@NotNull Token token, Long movieInstanceId);

    /**
     * 清除剧本的文件。当剧本已经删除后,剧本文件记录中引用数量为0时,就检查看是否有还存在其他记录引用文件,如果没有,则删除文件并删除记录。如果还有其他记录引用,则不删除并给出提示
     * @param ctx 剧本删除时记录的文件信息
     */
    void cleanMovieFile(MovieDeleteContext ctx);

    /**
     * 删除剧本.只有所有剧本实例都删除之后(或者从来没有发布过的剧本)才能删除剧本
     * @param token 操作用户
     * @param id 剧本id
     */
    MovieDeleteContext deleteMovie(Token token, Long id);

    MovieInstance movieDetail(@NotNull Token token, @Nullable Long id, @Nullable String deviceCode);

    MovieInstance movieDetail(@NotNull Token token, @Nullable Long id, @Nullable String version, @Nullable String deviceCode);

    /***
     * 查询剧本版本列表
     * @param token 操作用户
     * @param pageParam 分页参数
     * @param sortParam 排序参数
     * @param listParam 列表过滤参数
     * @return 分页对象
     */
    PageVo<MovieVo> versions(Token token, PageParam pageParam, SortParam sortParam, MovieVersionListParam listParam);

    /**
     * 查询多个剧本的最新版本实例信息
     * @param movieIds 剧本id列表,不是剧本实例的id
     * @return 剧本对应最新版本的实例信息
     */
    List<MovieVo> latestMovies(Long[] movieIds);
}
